/*
* sim-profile.c - sample functional simulator implementation w/ profiling
*
* This file is a part of the SimpleScalar tool suite written by
* Todd M. Austin as a part of the Multiscalar Research Project.
*  
* The tool suite is currently maintained by Doug Burger and Todd M. Austin.
* 
* Copyright (C) 1994, 1995, 1996, 1997, 1998 by Todd M. Austin
*
* This source file is distributed "as is" in the hope that it will be
* useful.  The tool set comes with no warranty, and no author or
* distributor accepts any responsibility for the consequences of its
* use. 
* 
* Everyone is granted permission to copy, modify and redistribute
* this tool set under the following conditions:
* 
*    This source code is distributed for non-commercial use only. 
*    Please contact the maintainer for restrictions applying to 
*    commercial use.
*
*    Permission is granted to anyone to make or distribute copies
*    of this source code, either as received or modified, in any
*    medium, provided that all copyright notices, permission and
*    nonwarranty notices are preserved, and that the distributor
*    grants the recipient permission for further redistribution as
*    permitted by this document.
*
*    Permission is granted to distribute this file in compiled
*    or executable form under the same conditions that apply for
*    source code, provided that either:
*
*    A. it is accompanied by the corresponding machine-readable
*       source code,
*    B. it is accompanied by a written offer, with no time limit,
*       to give anyone a machine-readable copy of the corresponding
*       source code in return for reimbursement of the cost of
*       distribution.  This written offer must permit verbatim
*       duplication by anyone, or
*    C. it is distributed by someone who received only the
*       executable form, and is accompanied by a copy of the
*       written offer of source code that they received concurrently.
*
* In other words, you are welcome to use, share and improve this
* source file.  You are forbidden to forbid anyone else to use, share
* and improve what you give them.
*
* INTERNET: dburger@cs.wisc.edu
* US Mail:  1210 W. Dayton Street, Madison, WI 53706
*
* $Id: sim-profile.c,v 1.1.1.1 2000/11/29 14:53:54 cu-cs Exp $
*
* $Log: sim-profile.c,v $
* Revision 1.1.1.1  2000/11/29 14:53:54  cu-cs
* Grand unification of arm sources.
*
*
* Revision 1.1.1.1.2.1  2000/11/14 05:32:22  taustin
* Sim-profile now works for ARM (mostly).
*
* Revision 1.1.1.1  2000/05/26 15:18:59  taustin
* SimpleScalar Tool Set
*
*
* Revision 1.4  1999/12/31 18:53:04  taustin
* quad_t naming conflicts removed
*
* Revision 1.3  1999/12/13 18:46:51  taustin
* cross endian execution support added
*
* Revision 1.2  1998/08/27 16:37:03  taustin
* implemented host interface description in host.h
* added target interface support
* added support for register and memory contexts
* instruction predecoding moved to loader module
* Alpha target support added
* added support for qword's
* added fault support
* added option ("-max:inst") to limit number of instructions analyzed
* added target-dependent myprintf() support
*
* Revision 1.1  1997/03/11  01:33:36  taustin
* Initial revision
*
*
*/

#include <stdio.h>
#include <stdlib.h>
#include <math.h>

#include "host.h"
#include "misc.h"
#include "machine.h"
#include "regs.h"
#include "memory.h"
#include "loader.h"
#include "syscall.h"
#include "dlite.h"
#include "symbol.h"
#include "options.h"
#include "stats.h"
#include "sim.h"

/*
* This file implements a functional simulator with profiling support.  Run
* with the `-h' flag to see profiling options available.
*/

p_branchInfo root_branchInfo = NULL;
p_branchInfo end_branchInfo = NULL;
unsigned long RAWCount = 0;
unsigned long OptRAWCount = 0;
//struct setAddr * AllAccessAddrs = NULL;
//struct setAddr * AllEntryAddrs = NULL;

/* simulated registers */
static struct regs_t regs;

/* simulated memory */
static struct mem_t *mem = NULL;

/* track number of refs */
static counter_t sim_num_refs = 0;

/* maximum number of inst's to execute */
static unsigned int max_insts;

/* profiling options */
static int prof_all /* = FALSE */;
static int prof_ic /* = FALSE */;
static int prof_inst /* = FALSE */;
static int prof_bc /* = FALSE */;
static int prof_am /* = FALSE */;
static int prof_seg /* = FALSE */;
static int prof_tsyms /* = FALSE */;
static int prof_dsyms /* = FALSE */;
static int load_locals /* = FALSE */;
static int prof_taddr /* = FALSE */;

/* text-based stat profiles */
#define MAX_PCSTAT_VARS 8
static int pcstat_nelt = 0;
static char *pcstat_vars[MAX_PCSTAT_VARS];

/* Add by cyong: find the addr1 to addr2 from branchInfo */

p_branchInfo fineBranchInfo(md_addr_t * addr1, md_addr_t addr2)
{
	int i;
	char flag=0;
	p_branchInfo iter_p = root_branchInfo;
	while(iter_p != NULL)
	{
		if(iter_p->NextPC == addr2)
		{
			flag = 1;
			for(i=0;i<N_CYCLE;i++)
			{
				if(iter_p->PC[i] != addr1[i])
				{
					flag = 0;
					break;
				}
			}
			if(flag)
				return iter_p;
			else
				iter_p = iter_p->nextInfo;
		}
		else
		{
			iter_p = iter_p->nextInfo;
		}
	}
	return iter_p;
}
/* Add the BranchInfo to the list */
p_branchInfo AddBranchInfo(md_addr_t * addr1, md_addr_t addr2, char ** names)
{
	int i;
	p_branchInfo entire = (branchInfo *) malloc (sizeof (branchInfo));
	for(i=0;i<N_CYCLE;i++)
	{
		entire->PC[i] = addr1[i];
		entire->a[i] = names[i];
	}
	entire->a[N_CYCLE] = names[N_CYCLE];
	entire->NextPC = addr2;
	entire->frequent = 1;
	entire->nextInfo = NULL;
	entire->type = 5;
	if(root_branchInfo == NULL)
	{
		root_branchInfo = entire;
		end_branchInfo = entire;
	}
	else
	{
		end_branchInfo->nextInfo = entire;
		end_branchInfo = entire;
	}
	return entire;
}

/* Add the access PC */

/*
p_setAddr AddAccessAddr(struct setAddr ** setEntire, md_addr_t addr2)
{
p_setAddr tmpAddr = *setEntire;
p_setAddr super = tmpAddr;
while(tmpAddr != NULL)
{
if(tmpAddr->addr == addr2)
return tmpAddr;
super = tmpAddr;
tmpAddr = tmpAddr->nextAddr;
}
tmpAddr = (p_setAddr) malloc(sizeof(setAddr));
tmpAddr->addr = addr2;
tmpAddr->nextAddr = NULL;
if(super == NULL)
*setEntire = tmpAddr;
else
super->nextAddr = tmpAddr;
return tmpAddr;
}*/
/* end */
/* register simulator-specific options */
void
	sim_reg_options(struct opt_odb_t *odb)
{
	opt_reg_header(odb, 
		"sim-profile: This simulator implements a functional simulator with\n"
		"profiling support.  Run with the `-h' flag to see profiling options\n"
		"available.\n"
		);

	/* instruction limit */
	opt_reg_uint(odb, "-max:inst", "maximum number of inst's to execute",
		&max_insts, /* default */0,
		/* print */TRUE, /* format */NULL);

	opt_reg_flag(odb, "-all", "enable all profile options",
		&prof_all, /* default */FALSE, /* print */TRUE, NULL);

	opt_reg_flag(odb, "-iclass", "enable instruction class profiling",
		&prof_ic, /* default */FALSE, /* print */TRUE, NULL);

	opt_reg_flag(odb, "-iprof", "enable instruction profiling",
		&prof_inst, /* default */FALSE, /* print */TRUE, NULL);

	opt_reg_flag(odb, "-brprof", "enable branch instruction profiling",
		&prof_bc, /* default */FALSE, /* print */TRUE, NULL);

	opt_reg_flag(odb, "-amprof", "enable address mode profiling",
		&prof_am, /* default */FALSE, /* print */TRUE, NULL);

	opt_reg_flag(odb, "-segprof", "enable load/store address segment profiling",
		&prof_seg, /* default */FALSE, /* print */TRUE, NULL);

	opt_reg_flag(odb, "-tsymprof", "enable text symbol profiling",
		&prof_tsyms, /* default */FALSE, /* print */TRUE, NULL);

	opt_reg_flag(odb, "-taddrprof", "enable text address profiling",
		&prof_taddr, /* default */FALSE, /* print */TRUE, NULL);

	opt_reg_flag(odb, "-dsymprof", "enable data symbol profiling",
		&prof_dsyms, /* default */FALSE, /* print */TRUE, NULL);

	opt_reg_flag(odb, "-internal",
		"include compiler-internal symbols during symbol profiling",
		&load_locals, /* default */FALSE, /* print */TRUE, NULL);

	opt_reg_string_list(odb, "-pcstat",
		"profile stat(s) against text addr's (mult uses ok)",
		pcstat_vars, MAX_PCSTAT_VARS, &pcstat_nelt, NULL,
		/* !print */FALSE, /* format */NULL, /* accrue */TRUE);
}

/* check simulator-specific option values */
void
	sim_check_options(struct opt_odb_t *odb, int argc, char **argv)
{
	if (prof_all)
	{
		/* enable all options */
		prof_ic = TRUE;
		prof_inst = TRUE;
		prof_bc = TRUE;
		prof_am = TRUE;
		prof_seg = TRUE;
		prof_tsyms = TRUE;
		prof_dsyms = TRUE;
		prof_taddr = TRUE;
	}
}

/* instruction classes */
enum inst_class_t {
	ic_load,		/* load inst */
	ic_store,		/* store inst */
	ic_uncond,		/* uncond branch */
	ic_cond,		/* cond branch */
	ic_icomp,		/* all other integer computation */
	ic_fcomp,		/* all floating point computation */
	ic_trap,		/* system call */
	ic_NUM
};

/* instruction class strings */
static char *inst_class_str[ic_NUM] = {
	"load",		/* load inst */
	"store",		/* store inst */
	"uncond branch",	/* uncond branch */
	"cond branch",	/* cond branch */
	"int computation",	/* all other integer computation */
	"fp computation",	/* all floating point computation */
	"trap"		/* system call */
};

/* instruction class profile */
static struct stat_stat_t *ic_prof = NULL;

/* instruction description strings */
static char *inst_str[OP_MAX];

/* instruction profile */
static struct stat_stat_t *inst_prof = NULL;

/* branch class profile */
enum branch_class_t {
	bc_uncond_dir,	/* direct unconditional branch */
	bc_cond_dir,		/* direct conditional branch */
	bc_call_dir,		/* direct functional call */
	bc_uncond_indir,	/* indirect unconditional branch */
	bc_cond_indir,	/* indirect conditional branch */
	bc_call_indir,	/* indirect function call */
	bc_NUM
};

/* branch class description strings */
static char *branch_class_str[bc_NUM] = {
	"uncond direct",	/* direct unconditional branch */
	"cond direct",	/* direct conditional branch */
	"call direct",	/* direct functional call */
	"uncond indirect",	/* indirect unconditional branch */
	"cond indirect",	/* indirect conditional branch */
	"call indirect"	/* indirect function call */
};

/* branch profile */
static struct stat_stat_t *bc_prof = NULL;

/* addressing mode profile */
static struct stat_stat_t *am_prof = NULL;

/* address segments */
enum addr_seg_t {
	seg_data,		/* data segment */
	seg_heap,		/* heap segment */
	seg_stack,		/* stack segment */
	seg_text,		/* text segment */
	seg_NUM
};

/* address segment strings */
static char *addr_seg_str[seg_NUM] = {
	"data segment",	/* data segment */
	"heap segment",	/* heap segment */
	"stack segment",	/* stack segment */
	"text segment",	/* text segment */
};

/* address segment profile */
static struct stat_stat_t *seg_prof = NULL;

/* bind ADDR to the segment it references */
static enum addr_seg_t			/* segment referenced by ADDR */
	bind_to_seg(md_addr_t addr)		/* address to bind to a segment */
{
	if (ld_data_base <= addr && addr < (ld_data_base + ld_data_size))
	return seg_data;
	else if ((ld_data_base + ld_data_size) <= addr && addr < ld_brk_point)
		return seg_heap;
	/* FIXME: ouch! */
	else if ((ld_stack_base - (16*1024*1024)) <= addr && addr < ld_stack_base)
		return seg_stack;
	else if (ld_text_base <= addr && addr < (ld_text_base + ld_text_size))
		return seg_text;
	else
		;
	//panic((char *)("cannot bind address to segment"));
}

/* text symbol profile */
static struct stat_stat_t *tsym_prof = NULL;
static char **tsym_names = NULL;


/* data symbol profile */
static struct stat_stat_t *dsym_prof = NULL;
static char **dsym_names = NULL;

/* text address profile */
static struct stat_stat_t *taddr_prof = NULL;

/* text-based stat profiles */
static struct stat_stat_t *pcstat_stats[MAX_PCSTAT_VARS];
static counter_t pcstat_lastvals[MAX_PCSTAT_VARS];
static struct stat_stat_t *pcstat_sdists[MAX_PCSTAT_VARS];

/* wedge all stat values into a counter_t */
#define STATVAL(STAT)							\
	((STAT)->sc == sc_int							\
	? (counter_t)*((STAT)->variant.for_int.var)				\
	: ((STAT)->sc == sc_uint						\
	? (counter_t)*((STAT)->variant.for_uint.var)			\
	: ((STAT)->sc == sc_counter					\
	? *((STAT)->variant.for_counter.var)				\
	: (0, 0))))

/* register simulator-specific statistics */
void
	sim_reg_stats(struct stat_sdb_t *sdb)
{
	int i;

	stat_reg_counter(sdb, "sim_num_insn",
		"total number of instructions executed",
		&sim_num_insn, sim_num_insn, NULL);
	stat_reg_counter(sdb, "sim_num_refs",
		"total number of loads and stores executed",
		&sim_num_refs, 0, NULL);
	stat_reg_int(sdb, "sim_elapsed_time",
		"total simulation time in seconds",
		&sim_elapsed_time, 0, NULL);
	stat_reg_formula(sdb, "sim_inst_rate",
		"simulation speed (in insts/sec)",
		"sim_num_insn / sim_elapsed_time", NULL);

	if (prof_ic)
	{
		/* instruction class profile */
		ic_prof = stat_reg_dist(sdb, "sim_inst_class_prof",
			"instruction class profile",
			/* initial value */0,
			/* array size */ic_NUM,
			/* bucket size */1,
			/* print format */(PF_COUNT|PF_PDF),
			/* format */NULL,
			/* index map */inst_class_str,
			/* print fn */NULL);
	}

	if (prof_inst)
	{
		int i;
		char buf[512];

		/* conjure up appropriate instruction description strings */
		for (i=0; i < /* skip NA */OP_MAX-1; i++)
		{
			sprintf(buf, "%-8s %-6s", md_op2name[i+1], md_op2format[i+1]);
			inst_str[i] = mystrdup(buf);
		}

		/* instruction profile */
		inst_prof = stat_reg_dist(sdb, "sim_inst_prof",
			"instruction profile",
			/* initial value */0,
			/* array size */ /* skip NA */OP_MAX-1,
			/* bucket size */1,
			/* print format */(PF_COUNT|PF_PDF),
			/* format */NULL,
			/* index map */inst_str,
			/* print fn */NULL);
	}

	if (prof_bc)
	{
		/* instruction branch profile */
		bc_prof = stat_reg_dist(sdb, "sim_branch_prof",
			"branch instruction profile",
			/* initial value */0,
			/* array size */bc_NUM,
			/* bucket size */1,
			/* print format */(PF_COUNT|PF_PDF),
			/* format */NULL,
			/* index map */branch_class_str,
			/* print fn */NULL);
	}

	if (prof_am)
	{
		/* instruction branch profile */
		am_prof = stat_reg_dist(sdb, "sim_addr_mode_prof",
			"addressing mode profile",
			/* initial value */0,
			/* array size */md_amode_NUM,
			/* bucket size */1,
			/* print format */(PF_COUNT|PF_PDF),
			/* format */NULL,
			/* index map */md_amode_str,
			/* print fn */NULL);
	}

	if (prof_seg)
	{
		/* instruction branch profile */
		seg_prof = stat_reg_dist(sdb, "sim_addr_seg_prof",
			"load/store address segment profile",
			/* initial value */0,
			/* array size */seg_NUM,
			/* bucket size */1,
			/* print format */(PF_COUNT|PF_PDF),
			/* format */NULL,
			/* index map */addr_seg_str,
			/* print fn */NULL);
	}

	if (prof_tsyms && sym_ntextsyms != 0)
	{
		int i;

		/* load program symbols */
		sym_loadsyms(ld_prog_fname, load_locals);

		/* conjure up appropriate instruction description strings */
		tsym_names = (char **)calloc(sym_ntextsyms, sizeof(char *));

		for (i=0; i < sym_ntextsyms; i++)
			tsym_names[i] = sym_textsyms[i]->name;

		/* text symbol profile */
		tsym_prof = stat_reg_dist(sdb, "sim_text_sym_prof",
			"text symbol profile",
			/* initial value */0,
			/* array size */sym_ntextsyms,
			/* bucket size */1,
			/* print format */(PF_COUNT|PF_PDF),
			/* format */NULL,
			/* index map */tsym_names,
			/* print fn */NULL);
	}

	if (prof_dsyms && sym_ndatasyms != 0)
	{
		int i;

		/* load program symbols */
		sym_loadsyms(ld_prog_fname, load_locals);

		/* conjure up appropriate instruction description strings */
		dsym_names = (char **)calloc(sym_ndatasyms, sizeof(char *));

		for (i=0; i < sym_ndatasyms; i++)
			dsym_names[i] = sym_datasyms[i]->name;

		/* data symbol profile */
		dsym_prof = stat_reg_dist(sdb, "sim_data_sym_prof",
			"data symbol profile",
			/* initial value */0,
			/* array size */sym_ndatasyms,
			/* bucket size */1,
			/* print format */(PF_COUNT|PF_PDF),
			/* format */NULL,
			/* index map */dsym_names,
			/* print fn */NULL);
	}

	if (prof_taddr)
	{
		/* text address profile (sparse profile), NOTE: a dense print format
		is used, its more difficult to read, but the profiles are *much*
		smaller, I've assumed that the profiles are read by programs, at
		least for your sake I hope this is the case!! */
		taddr_prof = stat_reg_sdist(sdb, "sim_text_addr_prof",
			"text address profile",
			/* initial value */0,
			/* print format */(PF_COUNT|PF_PDF),
			/* format */"0x%p %u %.2f",
			/* print fn */NULL);
	}

	for (i=0; i<pcstat_nelt; i++)
	{
		char buf[512], buf1[512];
		struct stat_stat_t *stat;

		/* track the named statistical variable by text address */

		/* find it... */
		stat = stat_find_stat(sdb, pcstat_vars[i]);
		if (!stat)
			//fatal("cannot locate any statistic named `%s'", pcstat_vars[i]);
			;

		/* stat must be an integral type */
		if (stat->sc != sc_int && stat->sc != sc_uint && stat->sc != sc_counter)
			//fatal("`-pcstat' statistical variable `%s' is not an integral type",
			//      stat->name);
			;

		/* register this stat */
		pcstat_stats[i] = stat;
		pcstat_lastvals[i] = STATVAL(stat);

		/* declare the sparce text distribution */
		sprintf(buf, "%s_by_pc", stat->name);
		sprintf(buf1, "%s (by text address)", stat->desc);
		pcstat_sdists[i] = stat_reg_sdist(sdb, buf, buf1,
			/* initial value */0,
			/* print format */(PF_COUNT|PF_PDF),
			/* format */"0x%p %u %.2f",
			/* print fn */NULL);
	}
	ld_reg_stats(sdb);
	mem_reg_stats(mem, sdb);
}

/* initialize the simulator */
void
	sim_init(void)
{
	sim_num_refs = 0;

	/* allocate and initialize register file */
	regs_init(&regs);

	/* allocate and initialize memory space */
	mem = mem_create("mem");
	mem_init(mem);
}

/* local machine state accessor */
static char *					/* err str, NULL for no err */
	profile_mstate_obj(FILE *stream,		/* output stream */
	char *cmd,			/* optional command string */
struct regs_t *regs,		/* registers to access */
struct mem_t *mem)		/* memory to access */
{
	/* just dump intermediate stats */
	sim_print_stats(stream);

	/* no error */
	return NULL;
}

/* load program into simulated state */
void
	sim_load_prog(char *fname,		/* program to load */
	int argc, char **argv,	/* program arguments */
	char **envp)		/* program environment */
{
	/* load program text and data, set up environment, memory, and regs */
	ld_load_prog(fname, argc, argv, envp, &regs, mem, TRUE);

	/* initialize the DLite debugger */
	dlite_init(md_reg_obj, dlite_mem_obj, profile_mstate_obj);
}


/* print simulator-specific configuration information */
void
	sim_aux_config(FILE *stream)		/* output stream */
{
	/* nothing currently */
}

/* dump simulator-specific auxiliary simulator statistics */
void
	sim_aux_stats(FILE *stream)		/* output stream */
{
}

/* un-initialize simulator-specific state */
void
	sim_uninit(void)
{
	/* nada */
}


/*
* configure the execution engine
*/

/*
* precise architected register accessors
*/

/* next program counter */
#define SET_NPC(EXPR)		(regs.regs_NPC = (EXPR))

/* current program counter */
#define CPC			(regs.regs_PC)

/* general purpose registers */
#define GPR(N)			(regs.regs_R[N])
#define SET_GPR(N,EXPR)                                                 \
	((void)(((N) == 15) ? setPC++ : 0), regs.regs_R[N] = (EXPR))

#if defined(TARGET_PISA)

/* floating point registers, L->word, F->single-prec, D->double-prec */
#define FPR_L(N)		(regs.regs_F.l[(N)])
#define SET_FPR_L(N,EXPR)	(regs.regs_F.l[(N)] = (EXPR))
#define FPR_F(N)		(regs.regs_F.f[(N)])
#define SET_FPR_F(N,EXPR)	(regs.regs_F.f[(N)] = (EXPR))
#define FPR_D(N)		(regs.regs_F.d[(N) >> 1])
#define SET_FPR_D(N,EXPR)	(regs.regs_F.d[(N) >> 1] = (EXPR))

/* miscellaneous register accessors */
#define SET_HI(EXPR)		(regs.regs_C.hi = (EXPR))
#define HI			(regs.regs_C.hi)
#define SET_LO(EXPR)		(regs.regs_C.lo = (EXPR))
#define LO			(regs.regs_C.lo)
#define FCC			(regs.regs_C.fcc)
#define SET_FCC(EXPR)		(regs.regs_C.fcc = (EXPR))

#elif defined(TARGET_ALPHA)

/* floating point registers, L->word, F->single-prec, D->double-prec */
#define FPR_Q(N)		(regs.regs_F.q[N])
#define SET_FPR_Q(N,EXPR)	(regs.regs_F.q[N] = (EXPR))
#define FPR(N)			(regs.regs_F.d[N])
#define SET_FPR(N,EXPR)		(regs.regs_F.d[N] = (EXPR))

/* miscellaneous register accessors */
#define FPCR			(regs.regs_C.fpcr)
#define SET_FPCR(EXPR)		(regs.regs_C.fpcr = (EXPR))
#define UNIQ			(regs.regs_C.uniq)
#define SET_UNIQ(EXPR)		(regs.regs_C.uniq = (EXPR))

#elif defined(TARGET_ARM)

/* processor status register */
#define PSR                     (regs.regs_C.cpsr)
#define SET_PSR(EXPR)           (regs.regs_C.cpsr = (EXPR))

#define PSR_N                   _PSR_N(regs.regs_C.cpsr)
#define SET_PSR_N(EXPR)         _SET_PSR_N(regs.regs_C.cpsr, (EXPR))
#define PSR_C                   _PSR_C(regs.regs_C.cpsr)
#define SET_PSR_C(EXPR)         _SET_PSR_C(regs.regs_C.cpsr, (EXPR))
#define PSR_Z                   _PSR_Z(regs.regs_C.cpsr)
#define SET_PSR_Z(EXPR)         _SET_PSR_Z(regs.regs_C.cpsr, (EXPR))
#define PSR_V                   _PSR_V(regs.regs_C.cpsr)
#define SET_PSR_V(EXPR)         _SET_PSR_V(regs.regs_C.cpsr, (EXPR))

/* floating point conversions */
union x { float f; word_t w; };
#define DTOW(D)         ({ union x fw; fw.f = (float)(D); fw.w; })
#define WTOD(W)         ({ union x fw; fw.w = (W); (double)fw.f; })
#define QSWP(Q)                                                         \
	((((Q) << 32) & ULL(0xffffffff00000000)) | (((Q) >> 32) & ULL(0xffffffff)))

/* floating point registers, L->word, F->single-prec, D->double-prec */
#define FPR_Q(N)                (QSWP(regs.regs_F.q[N]))
#define SET_FPR_Q(N,EXPR)       (regs.regs_F.q[N] = QSWP((EXPR)))
#define FPR_W(N)                (DTOW(regs.regs_F.d[N]))
#define SET_FPR_W(N,EXPR)       (regs.regs_F.d[N] = (WTOD(EXPR)))
#define FPR(N)                  (regs.regs_F.d[(N)])
#define SET_FPR(N,EXPR)         (regs.regs_F.d[(N)] = (EXPR))

/* miscellaneous register accessors */
#define FPSR                    (regs.regs_C.fpsr)
#define SET_FPSR(EXPR)          (regs.regs_C.fpsr = (EXPR))

#else
#error No ISA target defined...
#endif

/* precise architected memory state accessor macros */
#define READ_BYTE(SRC, FAULT)						\
	((FAULT) = md_fault_none, MEM_READ_BYTE(mem, addr = (SRC)))
#define READ_HALF(SRC, FAULT)						\
	((FAULT) = md_fault_none, MEM_READ_HALF(mem, addr = (SRC)))
#define READ_WORD(SRC, FAULT)						\
	((FAULT) = md_fault_none, MEM_READ_WORD(mem, addr = (SRC)))
#ifdef HOST_HAS_QWORD
#define READ_QWORD(SRC, FAULT)						\
	((FAULT) = md_fault_none, MEM_READ_QWORD(mem, addr = (SRC)))
#endif /* HOST_HAS_QWORD */

#define WRITE_BYTE(SRC, DST, FAULT)					\
	((FAULT) = md_fault_none, MEM_WRITE_BYTE(mem, addr = (DST), (SRC)))
#define WRITE_HALF(SRC, DST, FAULT)					\
	((FAULT) = md_fault_none, MEM_WRITE_HALF(mem, addr = (DST), (SRC)))
#define WRITE_WORD(SRC, DST, FAULT)					\
	((FAULT) = md_fault_none, MEM_WRITE_WORD(mem, addr = (DST), (SRC)))
#ifdef HOST_HAS_QWORD
#define WRITE_QWORD(SRC, DST, FAULT)					\
	((FAULT) = md_fault_none, MEM_WRITE_QWORD(mem, addr = (DST), (SRC)))
#endif /* HOST_HAS_QWORD */

/* system call handler macro */
#define SYSCALL(INST)	sys_syscall(&regs, mem_access, mem, INST, TRUE)


/* addressing mode FSM (dest of last LUI, used for decoding addr modes) */
static unsigned int fsm = 0;

/* Add by cyong */
map<md_addr_t,CY_pBlockInfo> * cy_HotBlocks = NULL;
map<md_addr_t,CY_pInstructionInfo> * cy_AddrInstruction=NULL;
unsigned long missAccess;
unsigned long cur_usedIntReg;/**/
unsigned long pre_usedIntReg[N_CYCLE+2];/**/
unsigned long cur_defIntReg;/**/
unsigned long pre_defIntReg[N_CYCLE+2];/**/
unsigned long cur_defFlagReg;
unsigned long cur_usedFlagReg;
set<md_addr_t> * allEntryAddrs = NULL;
list<md_addr_t> cy_processPC;
double saveRAW;
double costRollback;
char cy_iFlag;
unsigned long cy_iValue;
unsigned long cy_totalRollback;
set<md_addr_t> * cy_HotRAWInstPC=NULL;
char entryFlag;
static char *md_cond[16] =
{ "eq", "ne", "cs", "cc", "mi", "pl", "vs", "vc",
"hi", "ls", "ge", "lt", "gt", "le", "", "nv" };

char condExeFlag;
/* */
void readHotInst()
{
	char one_line[20];
	unsigned long addr;
	FILE * fp = fopen("hotInst.txt","r");
	if(fp != NULL)
	{
		cy_HotRAWInstPC = new set<md_addr_t>();
		while ( fgets(one_line, 20 ,fp) !=NULL)
		{
			one_line[10] = '\0';
			addr = (unsigned long)strtol(one_line,NULL,16);
			cy_HotRAWInstPC->insert(addr);
		}
		fclose(fp);
	}
}

void getRegInfo(md_inst_t inst, enum md_opcode op)
{
	char strFlag = 0;
	char i;
	char * s = MD_OP_NAME(op);
	char * s1 = s;
	cur_usedIntReg = 0;
	cur_defIntReg = 0;
	cy_iFlag = 0;
	if((s[0]=='s') && (s[1]=='t') && (s[2] == 'r' || s[2] == 'm'))
		strFlag = 1;/**/
	while(*s)
	{
		if(*s == '%')
		{
			s++;
			if(*s == 'c')
			{
				if(COND!=14)
				{
					cur_usedFlagReg = 0xf0000;
					condExeFlag = 1;
				}
				else
				{
					cur_usedFlagReg = 0;
					condExeFlag = 0;
				}
			}
		}
		s++;
	}
	if(((*(--s)) == 's') || strcmp("cmp%c",s1)==0 || strcmp("cmn%c",s1)==0)
	{
		cur_defFlagReg = 0xf0000;
	}
	else
	{
		cur_defFlagReg = 0;
	}
	s=MD_OP_FORMAT(op);
	while (*s)
	{
		if (*s == '%')
		{
			s++;
			switch (*s)
			{
				/*case 'c':
				if(COND!=14)
				condExeFlag = 1;
				else
				condExeFlag = 0;
				break;
				*/
			case 'd':
				if(strFlag)
					cur_usedIntReg=cur_usedIntReg|(1<<RD);
				else
					cur_defIntReg = cur_defIntReg|(1<<RD);
				//fprintf(stream, "r%d", RD);
				break;

			case 'v':
				if (URD < 16)
				{
					if(strFlag)
						cur_usedIntReg=cur_usedIntReg|(1<<RD);
					else
						cur_defIntReg = cur_defIntReg|(1<<RD);
					//fprintf(stream, "r%d", URD);
				}
				/*else
				fprintf(stream, "tmp%d", URD-16);*/
				break;

			case 'n':
				//fprintf(stream, "r%d", RN);
				if(strcmp(s1,"mul%c")==0||strcmp(s1,"mla%c")==0)
				{
					cur_defIntReg = cur_defIntReg|(1<<RN);
				}
				else
				{
					cur_usedIntReg = cur_usedIntReg|(1<<RN);
				}
				break;
			case 'u':
				if (URN < 16)
					cur_usedIntReg = cur_usedIntReg|(1<<URN);
				//fprintf(stream, "r%d", URN);
				//else
				//fprintf(stream, "tmp%d", URN-16);
				break;

			case 's':
				cur_usedIntReg = cur_usedIntReg|(1<<RS);
				//fprintf(stream, "r%d", RS);
				break;
			case 'w':
				cur_usedIntReg = cur_usedIntReg|(1<<RM);
				//fprintf(stream, "r%d", RM);
				break;
			case 'm':
				if (!SHIFT_REG && !SHIFT_SHAMT)
					cur_usedIntReg = cur_usedIntReg|(1<<RM);
				//fprintf(stream, "r%d", RM);
				else if (SHIFT_REG && !SHIFT_REG_PAD)
					//fprintf(stream,
					//	"r%d, %s r%d", RM, md_shift_type[SHIFT_TYPE], RS);
				{
					cur_usedIntReg = cur_usedIntReg|(1<<RM);
					cur_usedIntReg = cur_usedIntReg|(1<<RS);
				}
				else if (SHIFT_REG && SHIFT_REG_PAD)
					//fprintf(stream, "%s r%d (invalid pad!!!)",
					//	md_shift_type[SHIFT_TYPE], RS);
					cur_usedIntReg = cur_usedIntReg|(1<<RS);
				else
					//fprintf(stream,
					//	"r%d, %s #%d", RM, md_shift_type[SHIFT_TYPE], SHIFT_SHAMT);
					cur_usedIntReg = cur_usedIntReg|(1<<RM);
				break;

			case 'D':
				if(strFlag)
					cur_usedIntReg=cur_usedIntReg|(1<<(FD+20));
				else
					cur_defIntReg = cur_defIntReg|(1<<(FD+20));
				//fprintf(stream, "f%d", FD);
				break;
			case 'N':
				cur_usedIntReg=cur_usedIntReg|(1<<(FN+20));
				//fprintf(stream, "f%d", FN);
				break;
			case 'M':
				cur_usedIntReg=cur_usedIntReg|(1<<(FM+20));
				//fprintf(stream, "f%d", FM);
				break;

			case 'i'://表示为立即数，其值为ROTR(ROTIMM, ROTAMT << 1)
				cy_iValue=ROTR(ROTIMM, ROTAMT << 1);
				cy_iFlag = 1;
				break;
				/*case 'o':
				fprintf(stream, "%d", OFS);
				break;
				case 'h':
				fprintf(stream, "%d", HOFS);
				break;
				case 'O':
				fprintf(stream, "%d", FPOFS);
				break;
				case 'I':
				fprintf(stream, "%s", md_fp_imm[FPIMMBITS]);
				break;

				case 'a':
				fprintf(stream, "%s", md_pu_code[LDST_PU]);
				break;*/
			case 'R':
				//{
				//int first = TRUE;

				//fprintf(stream, "{");
				for (i=0; i < 16; i++)
				{
					if (REGLIST & (1 << i))
					{
						//if (!first)
						//  fprintf(stream, ",");
						//fprintf(stream, "r%d", i);
						cur_usedIntReg=cur_usedIntReg|(1<<i);
						//first = FALSE;
					}
				}
				//fprintf(stream, "}");
				//}
				break;
				/*case 't':
				fprintf(stream, "%s", md_ef_size[EF_SIZE]);
				break;
				case 'T':
				fprintf(stream, "%s", md_ef_size[LDST_EF_SIZE]);
				break;
				case 'r':
				fprintf(stream, "%s", md_gh_rndmode[GH_RNDMODE]);
				break;
				case 'C':
				fprintf(stream, "%d", FCNT ? FCNT : 4);
				break;

				case 'j':
				myfprintf(stream, "0x%p", pc + BOFS + 8);
				break;

				case 'S':
				fprintf(stream, "0x%08x", SYSCODE);
				break;
				case 'P':
				fprintf(stream, "%d", RS);
				break;
				case 'p':
				fprintf(stream, "%d", CPOPC);
				break;
				case 'g':
				fprintf(stream, "%d", CPEXT);
				break;
				*/
			default:
				//panic("unknown disassembler escape code `%c'", *s);
				;
			}
		}
		s++;
	}
}


CY_pInstructionInfo getRAWIns(md_addr_t addr, unsigned long defReg, unsigned long usedReg, string opName,char flag,unsigned long value)
{
	map<md_addr_t,CY_pInstructionInfo>::iterator addrIter;
	CY_pInstructionInfo tmp;
	addrIter = cy_AddrInstruction->find(addr);
	if(addrIter != cy_AddrInstruction->end())
	{
		return (*addrIter).second;
	}
	else
	{
		tmp = new CY_instructionInfo;
		tmp->addr = addr;
		tmp->prePC=tmp->sucPC = NULL;
		tmp->access=0;
		tmp->defReg = defReg | cur_defFlagReg;
		tmp->usedReg = usedReg | cur_usedFlagReg;
		tmp->opName = opName;
		tmp->parentInst = NULL;
		tmp->childInst = NULL;
		tmp->iFlag = flag;
		tmp->iValue = value;
		tmp->isRAWFlag = 0;
		tmp->entryFlag = entryFlag;
		cy_AddrInstruction->insert(pair<md_addr_t,CY_pInstructionInfo>(addr,tmp));
		return tmp;
	}
}
CY_pBlockInfo OptimizationForRAW(int index)
{
	md_addr_t beginAddr;
	list<md_addr_t>::iterator iter_processPC;
	CY_pBlockInfo tmp_block = new CY_blockInfo();
	CY_pInstructionInfo tmp_Ins;
	vector<CY_pInstructionInfo> * middleInsts = new vector<CY_pInstructionInfo>;
	vector<CY_pInstructionInfo> * savedInsts= new vector<CY_pInstructionInfo>;
	int cy_tmp_RAWCount = 0;
	
	tmp_block->access = 0;
	tmp_block->conditionFlag =false;
	tmp_block->index = index;
	tmp_block->initInsts = new vector<CY_pInstructionInfo>();
	for(iter_processPC = cy_processPC.begin();iter_processPC != cy_processPC.end();iter_processPC++)
	{
		beginAddr = (*iter_processPC);
		tmp_Ins = getRAWIns(beginAddr,cur_defIntReg,cur_usedIntReg,"null",cy_iFlag,cy_iValue);
		tmp_block->initInsts->push_back(tmp_Ins);
		//if(tmp_Ins->isRAWFlag)
		//	cy_tmp_RAWCount++;
	}
	tmp_block->initRAW =  CalculateRAWNumber(tmp_block->initInsts);
	tmp_block->optInsts = new vector<CY_pInstructionInfo>();
	
	
	InstReplace(tmp_block,middleInsts);	
	//构建基本块内指令依赖关系图	
	ConstructDG(middleInsts);
	ReschedleIns2(savedInsts,middleInsts);
	cy_tmp_RAWCount = CalculateRAWNumber(savedInsts); 
  ConstructDG(middleInsts);
	ReschedleIns(tmp_block,middleInsts);
	if(CalculateRAWNumber(tmp_block->optInsts)>cy_tmp_RAWCount)
	{
		tmp_block->optInsts->clear();
		tmp_block->optInsts->insert(tmp_block->optInsts->begin(),savedInsts->begin(),savedInsts->end());
		tmp_block->optRAW = cy_tmp_RAWCount;
	}
	else
	{
		tmp_block->optRAW = CalculateRAWNumber(tmp_block->optInsts);
	}
	//fprintf(stderr,"0x%08p(%d,%d)\n",cy_processPC.front(),tmp_block->initInsts->size(),tmp_block->initInsts->size());
	//tmp_block->optInsts->clear();
	//tmp_block->optInsts->insert(tmp_block->optInsts->begin(),tmp_block->initInsts->begin(),tmp_block->initInsts->end());
	
	if(tmp_block->optRAW>tmp_block->initRAW)
	{
		tmp_block->optInsts->clear();
		tmp_block->optRAW = tmp_block->initRAW;
		tmp_block->optInsts->insert(tmp_block->optInsts->begin(),tmp_block->initInsts->begin(),tmp_block->initInsts->end());
	}
	beginAddr = cy_processPC.front();
	//fprintf(stderr, "end");
	//getchar();
	cy_HotBlocks->insert(pair<md_addr_t,CY_pBlockInfo>(beginAddr,tmp_block));
	middleInsts->clear();
	savedInsts->clear();	
	delete middleInsts;
	delete savedInsts;
	return tmp_block;
}

void InstReplace(CY_pBlockInfo tmp_block,vector<CY_pInstructionInfo> * inst)
{
	CY_pInstructionInfo sourceInst;
	list<CY_pInstructionInfo> addOptInsts;
	int index_Inst = 0;
	char continueFg = 0;
	unsigned long predef = 0;
	int sourceLength = tmp_block->initInsts->size();
	for(; index_Inst<tmp_block->initInsts->size();index_Inst++)
	{
		sourceInst = tmp_block->initInsts->at(index_Inst);
		if((sourceInst->opName.find("add") != string::npos || sourceInst->opName.find("sub") != string::npos)
			&& sourceInst->iFlag)
		{
			if(continueFg == 1)
			{
				if(predef&(sourceInst->usedReg&0xfff0ffff))
				{
					addOptInsts.push_back(sourceInst);
				}
				else
				{
					continueFg = 0;
					ProcessAddInsts(&addOptInsts,inst);
					inst->push_back(sourceInst);
				}
			}
			else
			{
				continueFg = 1;
				addOptInsts.push_back(sourceInst);
			}
		}
		else
		{
			if(addOptInsts.size()>0)
				ProcessAddInsts(&addOptInsts,inst);
			inst->push_back(sourceInst);
			continueFg = 0;
		}
		predef = sourceInst->defReg&0xfff0ffff;
	}
	if(addOptInsts.size()>0)
		ProcessAddInsts(&addOptInsts,inst);
	for(index_Inst=inst->size();index_Inst<sourceLength;index_Inst++)
	{
		CY_pInstructionInfo replaceInst=new CY_instructionInfo;
		replaceInst->iFlag = 0;
		replaceInst->access = 0;
		replaceInst->childInst = NULL;
		replaceInst->defReg = 0;
		replaceInst->entryFlag = 0;
		replaceInst->isRAWFlag = 0;
		replaceInst->opName = "nop%c";
		replaceInst->parentInst = NULL;
		replaceInst->usedReg = 0;
		replaceInst->iValue = 0;
		replaceInst->prePC = 0;
		replaceInst->sucPC = 0;
		replaceInst->addr = 0;
		inst->push_back(replaceInst);
	}
}
void ProcessAddInsts(list<CY_pInstructionInfo> * processList,vector<CY_pInstructionInfo> * results)
{
	list<CY_pInstructionInfo>::iterator iter;
	CY_pInstructionInfo replaceInst;
	if(processList->size()<3)
	{
		for(iter = processList->begin();iter != processList->end();iter++)
		{
			results->push_back(*iter);
		}
	}
	else
	{
		unsigned long cy_im = 0;
		for(iter = processList->begin();iter != processList->end();iter++)
		{
			if((*iter)->opName.find("add") != string::npos)
			{
				cy_im += (*iter)->iValue;
			}
			else
			{
				cy_im -= (*iter)->iValue;
			}
		}
		replaceInst = new CY_instructionInfo;
		replaceInst->iFlag = 0;
		replaceInst->access = processList->front()->access;
		replaceInst->childInst = NULL;
		replaceInst->defReg = processList->back()->defReg;
		replaceInst->entryFlag = 0;
		replaceInst->isRAWFlag = 0;
		replaceInst->opName = "add%c";
		replaceInst->parentInst = NULL;
		replaceInst->usedReg = processList->front()->usedReg;
		replaceInst->iValue = cy_im;
		replaceInst->prePC = processList->front()->prePC;
		replaceInst->sucPC = processList->back()->sucPC;
		replaceInst->addr = 0;
		results->push_back(replaceInst);
	}
	processList->clear();
}

unsigned long CalculateRAWNumber(vector<CY_pInstructionInfo> * inst)
{
	unsigned long pre1 = 0;
	unsigned long pre2 = 0;
	int tmp_i;
	unsigned long tmp_numbers = 0;
	for(tmp_i = 0;tmp_i<inst->size();tmp_i++)
	{
		if((inst->at(tmp_i)->usedReg & 0xfff0ffff)&(pre1|pre2))
		{
			tmp_numbers ++;
		}
		pre1 = pre2;
		pre2 = (inst->at(tmp_i)->defReg & 0xfff0ffff);
	}
	return tmp_numbers;
}
vector<CY_pInstructionInfo> * DeleteNoEffectInst(vector<CY_pInstructionInfo> * inst)
{
	vector<CY_pInstructionInfo> * tmp_goodInst = new vector<CY_pInstructionInfo>();
	CY_pInstructionInfo k;
	int i;
	for(i=0;i<inst->size();i++)
	{
		k = inst->at(i);
		if(k->opName.find("b%c") != string::npos || k->opName.find("bl%c") != string::npos
			|| k->opName.find("cmp%c") != string::npos || k->opName.find("cmn%c") != string::npos
			|| k->opName.find("tst%c") != string::npos || k->opName.find("teq%c") != string::npos)
		{
			continue;
		}
		else
		{
			tmp_goodInst->push_back(k);
		}
	}
	return tmp_goodInst;
}

void ConstructDG(vector<CY_pInstructionInfo> * inst)
{
	CY_pInstructionInfo tmp_inst,tmp_inst2;
	unsigned long currentUsed,currentDef;
  for(int i=0;i<inst->size();i++)
	{
		tmp_inst = inst->at(i);
		if(tmp_inst->childInst != NULL)
		{
			tmp_inst->childInst->clear();
		}
		if(tmp_inst->parentInst != NULL)
		{
			tmp_inst->parentInst->clear();
		}
	}
	for(int i=1;i<inst->size();i++)
	{
		tmp_inst = inst->at(i);
		currentUsed = tmp_inst->usedReg;
		currentDef = tmp_inst->defReg;
		for(int j=i-1;j>=0;j--)
		{
			tmp_inst2 = inst->at(j);
			if((currentUsed & tmp_inst2->defReg)||(currentDef & tmp_inst2->usedReg)||(currentDef & tmp_inst2->defReg))
			{
				if(tmp_inst->parentInst == NULL)
				{
					tmp_inst->parentInst = new list<CY_pInstructionInfo>();
				}
				tmp_inst->parentInst->push_back(tmp_inst2);
				if(tmp_inst2->childInst == NULL)
				{
					tmp_inst2->childInst = new list<CY_pInstructionInfo>();
				}
				tmp_inst2->childInst->push_back(tmp_inst);
				currentUsed = currentUsed & (~tmp_inst2->defReg);
			}
		}
	}
}
void ReschedleIns2(vector<CY_pInstructionInfo> * saveList, vector<CY_pInstructionInfo> * inst)
{
	vector<unsigned long> tmp_defList;
	list<CY_pInstructionInfo> tmp_candidate_List;
	CY_pInstructionInfo tmp_inst;
	CY_pInstructionInfo tmp_cur_inst;
	list<CY_pInstructionInfo>::iterator list_iter;
	int tmp_i;
	int childNum =-1;
	if(saveList == NULL)
		saveList = new vector<CY_pInstructionInfo>();
	for(tmp_i=0;tmp_i<3;tmp_i++)
		tmp_defList.push_back(0);
	for(tmp_i=0;tmp_i<inst->size();tmp_i++)
	{
		tmp_inst = inst->at(tmp_i);
		if(tmp_inst->parentInst == NULL || tmp_inst->parentInst->size()==0)
		{
			tmp_candidate_List.push_back(tmp_inst);
		}
	}
	tmp_i = 0;

	while(tmp_candidate_List.size()>0)
	{
		tmp_i = 0;
		tmp_cur_inst = tmp_candidate_List.front();
		for(list_iter=tmp_candidate_List.begin();list_iter!=tmp_candidate_List.end();list_iter++)
		{
			tmp_inst = *(list_iter);
			if(!((tmp_inst->usedReg & 0xfff0ffff) & (tmp_defList.at(1)|tmp_defList.at(2))))
			{
				tmp_cur_inst = tmp_inst;
				if(tmp_inst->usedReg!=0 || tmp_inst->defReg != 0)
					break;
			}
		}
		saveList->push_back(tmp_cur_inst);
		tmp_candidate_List.remove(tmp_cur_inst);
		if(tmp_cur_inst->childInst != NULL)
		{
			for(list_iter = tmp_cur_inst->childInst->begin();list_iter != tmp_cur_inst->childInst->end();list_iter++)
			{
				(*list_iter)->parentInst->remove(tmp_cur_inst);
				if((*list_iter)->parentInst->size() == 0)
					tmp_candidate_List.push_back(*list_iter);
			}
		}
		tmp_defList.erase(tmp_defList.begin());
		tmp_defList.push_back(tmp_cur_inst->defReg);
	}
}
void ReschedleIns(CY_pBlockInfo tmp_block, vector<CY_pInstructionInfo> * inst)
{
	vector<unsigned long> tmp_defList;
	list<CY_pInstructionInfo> tmp_candidate_List;
	CY_pInstructionInfo tmp_inst;
	CY_pInstructionInfo tmp_cur_inst;
	list<CY_pInstructionInfo>::iterator list_iter;
	int tmp_i;
	int childNum =-1;
	if(tmp_block->optInsts == NULL)
		tmp_block->optInsts = new vector<CY_pInstructionInfo>();
	for(tmp_i=0;tmp_i<3;tmp_i++)
		tmp_defList.push_back(0);
	for(tmp_i=0;tmp_i<inst->size();tmp_i++)
	{
		tmp_inst = inst->at(tmp_i);
		if(tmp_inst->parentInst == NULL || tmp_inst->parentInst->size()==0)
		{
			tmp_candidate_List.push_back(tmp_inst);
		}
	}
	tmp_i = 0;

	while(tmp_candidate_List.size()>0)
	{
		tmp_i = 0;
		tmp_cur_inst = tmp_candidate_List.front();
		for(list_iter=tmp_candidate_List.begin();list_iter!=tmp_candidate_List.end();list_iter++)
		{
			tmp_inst = *(list_iter);
			/*if((tmp_inst->usedReg & 0xfff0ffff)==0 && (tmp_inst->defReg & 0xfff0ffff) != 0)
			{
				if(tmp_inst->childInst != NULL)
				{
					list<CY_pInstructionInfo>::iterator iter = tmp_inst->childInst->begin();
					char firstSelect = 0;
					for(;iter != tmp_inst->childInst->end();iter++)
					{
						if((*iter)->usedReg&tmp_inst->defReg&0xfff0ffff)
						{
							tmp_cur_inst = tmp_inst;
							firstSelect = 1;
							break;
						}
						else
						{
							;
						}
					}
					if(firstSelect)
						break;
				}
			}
			else */if((tmp_i == 0) && ((tmp_inst->usedReg & 0xfff0ffff) & tmp_defList.front()) 
				&& !((tmp_inst->usedReg & 0xfff0ffff) & (tmp_defList.at(1)|tmp_defList.at(2))))
			{
				tmp_cur_inst = tmp_inst;
				tmp_i = 1;
				break;
			}
			if((tmp_i == 0) && !((tmp_inst->usedReg & 0xfff0ffff) & (tmp_defList.at(1)|tmp_defList.at(2))))
			{
				if(childNum == -1)
				{
					if(tmp_inst->childInst != NULL)
					{
						childNum = tmp_inst->childInst->size();
					}
					else
					{
						childNum = 0;
					}
					tmp_cur_inst = tmp_inst;
				}
				else if(((tmp_inst->childInst) != NULL) && tmp_inst->childInst->size()>childNum)
				{
					tmp_cur_inst = tmp_inst;
					childNum = tmp_inst->childInst->size();
				}
			}
			/*if(!((tmp_inst->usedReg & 0xfff0ffff) & (tmp_defList.at(1)|tmp_defList.at(2))))
			{
				tmp_cur_inst = tmp_inst;
				if(tmp_inst->usedReg!=0 || tmp_inst->defReg != 0)
					break;
			}*/
		}
		tmp_block->optInsts->push_back(tmp_cur_inst);
		tmp_candidate_List.remove(tmp_cur_inst);
		if(tmp_cur_inst->childInst != NULL)
		{
			for(list_iter = tmp_cur_inst->childInst->begin();list_iter != tmp_cur_inst->childInst->end();list_iter++)
			{
				(*list_iter)->parentInst->remove(tmp_cur_inst);
				if((*list_iter)->parentInst->size() == 0)
					tmp_candidate_List.push_back(*list_iter);
			}
		}
		tmp_defList.erase(tmp_defList.begin());
		tmp_defList.push_back(tmp_cur_inst->defReg);
	}
}
/* end */
void SetCurrentReg(unsigned long * List, unsigned long current_Value, int number)
{
	int cy_i_tmp = 0;
	for(;cy_i_tmp<number-1;cy_i_tmp++)
	{
		List[cy_i_tmp] = List[cy_i_tmp+1];
	}
	List[number-1] = current_Value;
}

/* start simulation, program loaded, processor precise state initialized */
void
	sim_main(void)
{
	int i;
	md_inst_t inst;
	register md_addr_t addr;
	register int is_write;
	enum md_opcode op;
	unsigned int flags;
	enum md_fault_type fault;
	int setPC;
	/*Add by cyong  */
	unsigned long cy_for_RAW;
	int cy_i;
	char * names[N_CYCLE+1];//
	p_branchInfo tmp;
	md_addr_t prePC[N_CYCLE];//
	enum md_opcode preOp[N_CYCLE];//
	char preConExeFlag[N_CYCLE];//
	unsigned long cy_OptEndDefReg1 = 0;//用于记录优化后代码倒数第1条指令定义的寄存器
	unsigned long cy_OptEndDefReg2 = 0;//用于记录优化后代码倒数第2条指令定义的寄存器
	int cy_exitNum=0;//标记该代码是从优化后代码出来后的第几条代码
	list<md_addr_t> cy_PrePC;// for save the pre instructions of hot RAW instruction
	int cy_Flag = 0;// for get the hot blocks
	CY_pInstructionInfo cy_CurrentIns = NULL;
	CY_pInstructionInfo cy_CurrentHotIns = NULL;
	allEntryAddrs = new set<md_addr_t>();
	list<md_addr_t>::iterator cy_sucPC_iter;
	int cy_SourceIns;
	int cy_HotIndex;
	md_addr_t cy_HotPC;
	double cy_cur_saveRAW;
	double cy_cur_costRollback;
	int cy_conditonTranFlag;
	int cy_cur_inst;
	CY_pBlockInfo cy_curHotBlock=NULL;
	unsigned long tmp_savedRAW;
	unsigned long tmp_savedOptRAW;
	unsigned long beginAddr;
	char k_flag = 1;
	
	unsigned long cy_defRegForOpt[N_CYCLE+1];//用于保存优化后代码前N_CYCLE条语句定义的reg
	unsigned long cy_usedRegForOpt[N_CYCLE+1];//用于保存优化后代码前N_CYCLE条语句使用的reg
	
	entryFlag = 0;
	cy_HotBlocks = new map<md_addr_t,CY_pBlockInfo>();
	cy_AddrInstruction = new map<md_addr_t,CY_pInstructionInfo>();
	missAccess=0;
	//initial the hot Inst
	readHotInst();
	//initial the prePC
	for(cy_i = 0;cy_i<N_PREPC;cy_i++)
	{
		cy_PrePC.push_back(0);
	}
	//initial the define and use register and the opName
	for(cy_i=0;cy_i<N_CYCLE;cy_i++)
	{
		pre_defIntReg[cy_i] = 0;
		pre_usedIntReg[cy_i] = 0;
		prePC[cy_i] = 0;
		names[cy_i] = NULL;
		preOp[cy_i] = (enum md_opcode)0; 
		preConExeFlag[cy_i] = 0;
		cy_defRegForOpt[cy_i]=0;
		cy_usedRegForOpt[cy_i] = 0;
	}
	cy_defRegForOpt[cy_i]=0;
	cy_usedRegForOpt[cy_i] = 0;
	pre_defIntReg[cy_i] = 0;
	pre_defIntReg[cy_i +1]=0; 
	pre_usedIntReg[cy_i] = 0;
	pre_usedIntReg[cy_i +1]=0;
	names[N_CYCLE] = NULL;
	/* end */
	fprintf(stderr, "sim: ** starting functional simulation **\n");

	/* set up initial default next PC */
	regs.regs_NPC = regs.regs_PC + sizeof(md_inst_t);

	/* synchronize register files... */
	regs.regs_R[MD_REG_PC] = regs.regs_PC-sizeof(md_inst_t);

	/* check for DLite debugger entry condition */
	if (dlite_check_break(regs.regs_PC, /* no access */0, /* addr */0, 0, 0))
		dlite_main(regs.regs_PC - sizeof(md_inst_t), regs.regs_PC,
		sim_num_insn, &regs, mem);

	while (TRUE)
	{
		/* maintain $r0 semantics */
#ifndef TARGET_ARM
		regs.regs_R[MD_REG_ZERO] = 0;
#endif
#ifdef TARGET_ALPHA
		regs.regs_F.d[MD_REG_ZERO] = 0.0;
#endif /* TARGET_ALPHA */

		/* get the next instruction to execute */
		MD_FETCH_INST(inst, mem, regs.regs_PC);

		if (verbose)
		{
			myfprintf(stderr, "%10n @ 0x%08p: ", sim_num_insn, regs.regs_PC);
			md_print_insn(inst, regs.regs_PC, stderr);
			fprintf(stderr, "\n");
			/* fflush(stderr); */
		}


		/* keep an instruction count */
		sim_num_insn++;

		/* set default reference address and access mode */
		addr = 0; is_write = FALSE;

		/* set default fault - none */
		fault = md_fault_none;

		/* decode the instruction */

		MD_SET_OPCODE(op, inst);
		/* Add by cyong */
		//fprintf(stderr,"current operands is: %s\n",MD_OP_FORMAT(op));

		/*if( regs.regs_PC == 0x0002f3f8)
		printf("cyong tttttttttttt 0x0002f3f8 %d",COND);*/
		getRegInfo( inst, op );
		//AddAccessAddr(&AllAccessAddrs, regs.regs_PC );/* 添加访问的PC*/
		if(entryFlag)
			allEntryAddrs->insert(regs.regs_PC);
		for(cy_i=0;cy_i<N_CYCLE;cy_i++)
			names[cy_i] = names[cy_i+1];
		names[cy_i] = MD_OP_NAME(op);
		//fprintf(stderr,"%s:%s\n",names[cy_i],MD_OP_FORMAT(op));
		cy_for_RAW = pre_defIntReg[2];
		for(cy_i=3; cy_i<N_CYCLE+2; cy_i++)
			cy_for_RAW |= pre_defIntReg[cy_i];
		if(cy_for_RAW & cur_usedIntReg)
		{
			RAWCount++;
			tmp = fineBranchInfo(prePC, regs.regs_PC);

			if(tmp == NULL)
			{
				tmp = AddBranchInfo(prePC, regs.regs_PC, names);
				for(cy_i=0;cy_i<N_CYCLE;cy_i++)
				{
					tmp->preConExeFlag[cy_i] = preConExeFlag[cy_i];
					tmp->preOp[cy_i] = preOp[cy_i];
				}
				tmp->preConExeFlag[cy_i] = condExeFlag;
				tmp->preOp[cy_i] = op;
				for(cy_i=0;cy_i<=N_CYCLE;cy_i++)
				{
					if(strcmp(names[cy_i],"b%c")==0 || strcmp(names[cy_i],"bl%c")==0)
					{
						tmp->type = 3;
						break;
					}
				}
				if(tmp->type == 5)
				{
					if(condExeFlag || tmp->preConExeFlag[N_CYCLE-1] || tmp->preConExeFlag[N_CYCLE-2])
					{
						tmp->type = 2;
					}
					else if((pre_defIntReg[N_CYCLE+1]&cur_usedIntReg)&&(strcmp(names[N_CYCLE],"add%c")==0||strcmp(names[N_CYCLE],"sub%c")==0)
						&& (pre_defIntReg[N_CYCLE]&pre_usedIntReg[N_CYCLE+1])&&(strcmp(names[N_CYCLE-1],"sub%c")==0||strcmp(names[N_CYCLE-1],"add%c")==0))
					{
						tmp->type = 4;
					}
					else if((((pre_defIntReg[0]|pre_defIntReg[1])& cur_usedIntReg)==0)|| (!((pre_defIntReg[N_CYCLE+1]&cur_usedIntReg) && (pre_defIntReg[N_CYCLE]&cur_usedIntReg))))
					{
						tmp->type = 1;
					}
				}
			}
			else
			{
				tmp->frequent += 1;
			}
		}
		for(cy_i=0;cy_i<N_CYCLE-1;cy_i++)
		{
			pre_defIntReg[cy_i] = pre_defIntReg[cy_i+1];
			pre_usedIntReg[cy_i] = pre_usedIntReg[cy_i+1];
			prePC[cy_i] = prePC[cy_i+1];
			preOp[cy_i] = preOp[cy_i+1]; 
			preConExeFlag[cy_i] = preConExeFlag[cy_i+1];
		}
		for(;cy_i<N_CYCLE+1;cy_i++)
		{
			pre_defIntReg[cy_i] = pre_defIntReg[cy_i+1];
			pre_usedIntReg[cy_i] = pre_usedIntReg[cy_i+1];
		}
		pre_defIntReg[N_CYCLE+1] = cur_defIntReg;
		pre_usedIntReg[N_CYCLE+1] = cur_usedIntReg;
		preOp[N_CYCLE-1] = op; 
		preConExeFlag[N_CYCLE-1] = condExeFlag;
		prePC[N_CYCLE-1] = regs.regs_PC;

		//printf("current instruction is: %u,%u\n",sim_num_insn,regs.regs_PC);
		//识别热点块
		cy_CurrentIns = getRAWIns(regs.regs_PC,cur_defIntReg,cur_usedIntReg,names[N_CYCLE],cy_iFlag,cy_iValue);
		if(entryFlag)
			cy_CurrentIns->entryFlag = 1;
		cy_CurrentIns->access++;
		if(cy_for_RAW & cur_usedIntReg)
			cy_CurrentIns->isRAWFlag = 1;
		if(cy_Flag != 4 )//先查找是否存在对应的匹配模式
		{
			//判断是否可以进入优化后的程序
			map<md_addr_t,CY_pBlockInfo>::iterator mapIter = cy_HotBlocks->find(regs.regs_PC);
			if(mapIter != cy_HotBlocks->end())
			{
				//可以进入，则多计算一次第二条语句是否同外部存在额外的RAW依赖关系
				//cy_exitNum=0;//清出口标记
				tmp_savedRAW = RAWCount;
				tmp_savedOptRAW = OptRAWCount;
				beginAddr = regs.regs_PC;
				cy_curHotBlock = (*mapIter).second;
				//判断第一条语句是否会增加额外的RAW语句
				/*if(cy_curHotBlock->optInsts->front()->usedReg & (cy_defRegForOpt[1]|cy_defRegForOpt[2]))
				{
					OptRAWCount++;
				}
				if((cy_curHotBlock->optInsts->at(1)->usedReg & cy_defRegForOpt[2])&& !(cy_curHotBlock->optInsts->at(1)->usedReg & cy_curHotBlock->optInsts->front()->defReg))
				{
					OptRAWCount++;
				}*/
				//访问次数加1
				cy_curHotBlock->access++;
				//增加该块内RAW访问
				//OptRAWCount += cy_curHotBlock->optRAW;
				//设置当前块信息
				cy_HotIndex = (*mapIter).second->index;
				cy_cur_inst = cy_SourceIns = (*mapIter).second->initInsts->size();
				cy_HotPC = ((*mapIter).second->initInsts->at(cy_HotIndex))->addr;
				//计算该块其他开销，暂时无用
				cy_cur_saveRAW = ((*mapIter).second->initInsts->size()+0.5*(*mapIter).second->initRAW)
					-((*mapIter).second->optInsts->size()+0.5*(*mapIter).second->optRAW);
				cy_cur_costRollback = (*mapIter).second->initInsts->size()+0.5*(*mapIter).second->initRAW;
				cy_conditonTranFlag = (*mapIter).second->conditionFlag;
				//设置标记，表示下条语句开始进入优化块
				cy_Flag = 4;
				
				//cy_CurrentHotIns = ((*mapIter).second->initInsts->at(cy_HotIndex));
			}
			else
			{
				if(cur_usedIntReg & (cy_defRegForOpt[1]|cy_defRegForOpt[2]))
				{
					OptRAWCount++;
				}
			}
		}
		//基本块内信息搜集
		/*if(cy_CurrentIns->isRAWFlag && (cy_Flag == 0))
		{
			map<md_addr_t,CY_pInstructionInfo>::iterator mp_iter;
			md_addr_t tmp_addr = regs.regs_PC;
			list<md_addr_t>::reverse_iterator rt;
			cy_CurrentHotIns = cy_CurrentIns;
			if(cy_CurrentHotIns->prePC == NULL)
			{
				cy_CurrentHotIns->prePC = new list<md_addr_t>();
			}
			else
			{
				cy_CurrentHotIns->prePC->clear();
			}
			for(rt = cy_PrePC.rbegin();rt != cy_PrePC.rend();rt++)
			{
				mp_iter = cy_AddrInstruction->find(*rt);
				if((tmp_addr-(*rt)==sizeof(md_inst_t))
					&& (mp_iter->second->opName!="b%c") && (mp_iter->second->opName != "bl%c"))
				{
					cy_CurrentHotIns->prePC->push_back(*rt);
					tmp_addr = *rt;
				}
				else
				{
					break;
				}
			}
			if(cy_CurrentHotIns->sucPC == NULL)//需要搜集后继基本块
			{
				cy_CurrentHotIns->sucPC = new list<md_addr_t>();
				cy_Flag = 1;
			}
			else//后继基本块已经在前期搜集好了，直接使用即可
			{
				cy_Flag = 3;
			}
		}
		else if(cy_Flag == 1)//处于搜集后继基本块阶段
		{
			if(cy_CurrentIns->opName.find("b%c")!=string::npos||cy_CurrentIns->opName.find("bl%c")!=string::npos)
			{
				cy_Flag = 3;//指令序列已经搜集好,标记可进行优化
			}
			else if(regs.regs_PC-cy_PrePC.back() == sizeof(md_addr_t))
			{
				cy_CurrentHotIns->sucPC->push_back(regs.regs_PC);
			}
			else
			{
				cy_Flag = 3;//指令序列已经搜集好,标记可进行优化
			}
		}*/
		if(cy_CurrentIns->isRAWFlag && (cy_Flag == 0) )
		{
			//if(((cy_HotRAWInstPC != NULL) && cy_HotRAWInstPC->find(regs.regs_PC)!=cy_HotRAWInstPC->end()) ||cy_CurrentIns->access> HOT_TH)
			//if(cy_HotRAWInstPC->find(regs.regs_PC)!=cy_HotRAWInstPC->end())
			if(cy_CurrentIns->access> HOT_TH)
			{
				/*myfprintf(stderr, "0 %10n @ 0x%08p: ", sim_num_insn, regs.regs_PC);
				md_print_insn(inst, regs.regs_PC, stderr);
				fprintf(stderr, "\n");
				getchar();*/
				map<md_addr_t,CY_pInstructionInfo>::iterator mp_iter;
				cy_CurrentHotIns = cy_CurrentIns;
				if(cy_CurrentIns->prePC == NULL)
				{
					list<md_addr_t>::reverse_iterator rt;
					cy_CurrentHotIns->prePC = new list<md_addr_t>();
					cy_CurrentHotIns->sucPC = new list<md_addr_t>();
					for(rt = cy_PrePC.rbegin();rt != cy_PrePC.rend();rt++)
					{
						mp_iter = cy_AddrInstruction->find(*rt);
						if((*rt) != regs.regs_PC && (*rt) != 0 && !(mp_iter->second->defReg & 0x8000) &&mp_iter->second->opName!="b%c" && mp_iter->second->opName != "bl%c" )
						{
							cy_CurrentHotIns->prePC->push_front((*rt));
							/*if(allEntryAddrs->find((*rt))!=allEntryAddrs->end())
								break;*/
						}
						else
						{
							break;
						}
					}
					if(cy_CurrentHotIns->prePC->size()<2 && cy_CurrentHotIns->prePC->size()>0)
					{
						if(cy_AddrInstruction->find(cy_CurrentHotIns->prePC->front())->second->defReg & cur_usedIntReg)
							cy_Flag = 1;
					}
					else if(cy_CurrentHotIns->prePC->size()>=2)
					{
						cy_Flag = 1;
					}
				}
				else
				{
					list<md_addr_t>::reverse_iterator rt;
					list<md_addr_t>::reverse_iterator rt2;
					
					int cy_tmp_size = cy_CurrentHotIns->prePC->size();
					int cy_tmp_currentNum = 0;
					for(rt = cy_PrePC.rbegin(),rt2 = cy_CurrentHotIns->prePC->rbegin();
						rt != cy_PrePC.rend(),rt2 != cy_CurrentHotIns->prePC->rend();rt++,rt2++)
					{
						if((*rt) != (*rt2) )
							break;
						else
						{
							mp_iter = cy_AddrInstruction->find(*rt);
							if(mp_iter->second->opName=="b%c" || mp_iter->second->opName == "bl%c")
							{
								break;
							}
							else
							{
								cy_tmp_currentNum++;
								if(allEntryAddrs->find((*rt2))!=allEntryAddrs->end())
								break;
							}
						}
					}
					for(cy_i=0;cy_i<cy_tmp_size-cy_tmp_currentNum;cy_i++)
					{
						cy_CurrentHotIns->prePC->pop_front();
					}
					cy_sucPC_iter = cy_CurrentHotIns->sucPC->begin();
					cy_Flag = 2;
				}
			}
		}
		else if(cy_Flag == 1)//准备后继指令序列
		{
			/*myfprintf(stderr, "1 %10n @ 0x%08p: ", sim_num_insn, regs.regs_PC);
			md_print_insn(inst, regs.regs_PC, stderr);
			fprintf(stderr, "\n");
			//getchar();*/
			if(cy_CurrentHotIns->sucPC->size()<N_SUCPC && !(strcmp(names[N_CYCLE],"b%c")==0 || strcmp(names[N_CYCLE],"bl%c")==0)
			  && !(cur_defIntReg&0x8000) /*&& (allEntryAddrs->find(regs.regs_PC)==allEntryAddrs->end())*/)
				cy_CurrentHotIns->sucPC->push_back(regs.regs_PC);
			else
				cy_Flag = 0;
		}
		else if(cy_Flag == 2)//比较后继指令，获得可优化序列进行优化
		{
			/*myfprintf(stderr, "2 %10n @ 0x%08p: ", sim_num_insn, regs.regs_PC);
			md_print_insn(inst, regs.regs_PC, stderr);
			fprintf(stderr, "\n");
			//getchar();*/
			if(cy_sucPC_iter != cy_CurrentHotIns->sucPC->end())
			{
				if((*cy_sucPC_iter)==regs.regs_PC)
				{
					cy_sucPC_iter++;
				}
				else
				{
					cy_CurrentHotIns->sucPC->erase(cy_sucPC_iter,cy_CurrentHotIns->sucPC->end());
					cy_Flag = 3;
				}
			}
			else
			{
				cy_Flag = 3;
			}
		}
		if(cy_Flag == 3)//优化指令序列
		{
			list<md_addr_t>::iterator iter;
			//md_addr_t beginAddr;
			cy_processPC.clear();
			for(iter = cy_CurrentHotIns->prePC->begin();iter != cy_CurrentHotIns->prePC->end();iter++)
			{
				cy_processPC.push_back((*iter));
			}
			cy_processPC.push_back(cy_CurrentHotIns->addr);
			for(iter = cy_CurrentHotIns->sucPC->begin();iter != cy_CurrentHotIns->sucPC->end();iter++)
			{
				cy_processPC.push_back((*iter));
			}
			if(cy_processPC.size()>3 && cy_HotBlocks->find(cy_CurrentHotIns->prePC->front()) == cy_HotBlocks->end())
				OptimizationForRAW(cy_CurrentHotIns->prePC->size());
			cy_Flag = 0;
		}
		if(cy_Flag == 4 )//处理优化指令块，主要用于过滤原始指令
		{
			int current_Index = cy_cur_inst-cy_SourceIns;//获得当前指令的执行次数
			if(current_Index<cy_curHotBlock->optInsts->size())
			{
				if(cy_curHotBlock->optInsts->at(current_Index)->usedReg & (cy_defRegForOpt[1]|cy_defRegForOpt[2]))
				{
					OptRAWCount++;
				}
				SetCurrentReg(cy_defRegForOpt,cy_curHotBlock->optInsts->at(current_Index)->defReg&0xfff0ffff,N_CYCLE+1);
				SetCurrentReg(cy_usedRegForOpt,cy_curHotBlock->optInsts->at(current_Index)->usedReg&0xfff0ffff,N_CYCLE+1);
			}
			cy_SourceIns--;
			if(cy_SourceIns == 0)//指令执行完毕，处理后续信息，统计出口位置的前两条语句是否会出现RAW
			{
				/*if(RAWCount != OptRAWCount && k_flag)
				{
					fprintf(stderr, "error in %u,%u,%u, %u,%u\n",beginAddr,sim_num_insn,regs.regs_PC,cy_curHotBlock->optInsts->size());
					k_flag = 0;
				}*/
				//如果该基本块的RAW比原始更多，则换回原序列执行
				//if(RAWCount-tmp_savedRAW<OptRAWCount-tmp_savedOptRAW)
				//	OptRAWCount = tmp_savedOptRAW + RAWCount-tmp_savedRAW;
				//cy_exitNum = 2;
				//cy_OptEndDefReg1 = cy_curHotBlock->optInsts->at(cy_curHotBlock->optInsts->size()-1)->defReg&0xfff0ffff;
				//if(cy_curHotBlock->optInsts->size()>1)
				//	cy_OptEndDefReg2 = cy_curHotBlock->optInsts->at(cy_curHotBlock->optInsts->size()-2)->defReg&0xfff0ffff;
				//else
				//	cy_OptEndDefReg2 = 0;
				cy_Flag = 0;
				saveRAW += cy_cur_saveRAW;
			}
			//专门针对基本块内时该情况不会出现
			/*else if(cy_curHotBlock->initInsts->at(cy_curHotBlock->initInsts->size()-cy_SourceIns)->addr != regs.regs_PC)
			{
				//cy_curHotBlock->access--;
				missAccess++;
				cy_totalRollback += cy_cur_inst;
				costRollback += cy_cur_costRollback;
				cy_Flag = 0;
			}
			if(cy_HotIndex == 0)
			{
				if(regs.regs_PC == cy_HotPC)
				{
					saveRAW += cy_cur_saveRAW;
				}
				else
				{
					cy_curHotBlock->access--;
					missAccess++;
					cy_totalRollback += cy_cur_inst;
					costRollback += cy_cur_costRollback;
					cy_Flag = 0;
				}
			}
			cy_SourceIns--;
			cy_HotIndex--;
			if(cy_SourceIns == 0)
			{
				cy_Flag = 0;
			}*/
		}
		else
		{
			SetCurrentReg(cy_defRegForOpt,cur_defIntReg&0xfff0ffff,N_CYCLE+1);
			SetCurrentReg(cy_usedRegForOpt,cur_usedIntReg&0xfff0ffff,N_CYCLE+1);
		}
		
		cy_PrePC.pop_front();
		cy_PrePC.push_back(regs.regs_PC);
		/*if((cy_defRegForOpt[0] != pre_defIntReg[1]) || (cy_defRegForOpt[1] != pre_defIntReg[2]) || (cy_defRegForOpt[2] != pre_defIntReg[3])||(cy_usedRegForOpt[0] != pre_usedIntReg[1]) || (cy_usedRegForOpt[1] != pre_usedIntReg[2]) || (cy_usedRegForOpt[2] != pre_usedIntReg[3]))
		{
			fprintf(stderr, "error in %u,%u,%u\n",sim_num_insn,regs.regs_PC);
			fprintf(stderr, "(%u,%u),(%u,%u),(%u,%u),(%u,%u),(%u,%u),(%u,%u)\n",cy_defRegForOpt[0],pre_defIntReg[1],cy_defRegForOpt[1],pre_defIntReg[2],cy_defRegForOpt[2],pre_defIntReg[3],cy_usedRegForOpt[0],pre_usedIntReg[1],cy_usedRegForOpt[1],pre_usedIntReg[2],cy_usedRegForOpt[2],pre_usedIntReg[3]);
		}*/
		//printf("cytest(RN=%d,RD=%d,RM=%d,RS=%d,%s %s\n",RN,RD,RM,RS,MD_OP_NAME(op),MD_OP_FORMAT(op));
		/* end */
		if (op == NA)
		{
			//fatal("bogus opcode detected @ 0x%08p", regs.regs_PC);
			;
		}
		setPC = 0;
		regs.regs_R[MD_REG_PC] = regs.regs_PC;

		/* execute the instruction */
		switch (op)
		{
#define DEFINST(OP,MSK,NAME,OPFORM,RES,FLAGS,O1,O2,O3,I1,I2,I3,I4)	\
		case OP:							\
		SYMCAT(OP,_IMPL);						\
		break;
#define DEFLINK(OP,MSK,NAME,MASK,SHIFT)					\
		case OP:							\
		//panic((char *)("attempted to execute a linking opcode"));
			;
#define CONNECT(OP)
#define DECLARE_FAULT(FAULT)						\
			{ fault = (FAULT); break; }
#include "machine.def"
		default:
			//panic(((char *)"attempted to execute a bogus opcode"));
			;
		}
		/*Add by cyong */
		//printf("cytest(RN=%08p,RD=%d,RM=%d,RS=%d,DPRS=%08p, %s %s\n",GPR(RN),RD,RM,RS,PSR ,MD_OP_NAME(op),MD_OP_FORMAT(op));
		/* end */
		if (fault != md_fault_none)
		{
			//fatal("fault (%d) detected @ 0x%08p", fault, regs.regs_PC);
			;
		}
		if (setPC != 0/* regs.regs_R[MD_REG_PC] != regs.regs_PC */)//当为跳转指令时，setPC值被设置为对应的地址
			regs.regs_NPC = regs.regs_R[MD_REG_PC];

		if (MD_OP_FLAGS(op) & F_MEM)//是内存操作指令，即load/store指令
		{
			sim_num_refs++;
			if (MD_OP_FLAGS(op) & F_STORE)
				is_write = TRUE;
		}

		/*
		* profile this instruction
		*/
		flags = MD_OP_FLAGS(op);
		/* Add by cyong */
		if (flags & F_CTRL)
			entryFlag = 1;
		else
			entryFlag = 0;
		/*  End  */
		if (prof_ic)
		{
			enum inst_class_t ic;

			/* compute instruction class */
			if (flags & F_LOAD)
				ic = ic_load;
			else if (flags & F_STORE)
				ic = ic_store;
#if 0
			else if (flags & F_UNCOND)
				ic = ic_uncond;
			else if (flags & F_COND)
				ic = ic_cond;      
#endif
			else if (flags & F_CTRL && COND == COND_AL)
				ic = ic_uncond;
			else if (flags & F_CTRL && COND != COND_AL)
				ic = ic_cond;
			else if (flags & F_ICOMP)
				ic = ic_icomp;
			else if (flags & F_FCOMP)
				ic = ic_fcomp;
			else if (flags & F_TRAP)
				ic = ic_trap;
			else{
				//panic((char *)("instruction has no class"));
				;}

			/* update instruction class profile */
			stat_add_sample(ic_prof, (int)ic);
		}

		if (prof_inst)
		{
			/* update instruction profile */
			stat_add_sample(inst_prof, (int)op - /* skip NA */1);
		}

#if FIXME
		if (prof_bc)
		{
			enum branch_class_t bc;

			/* compute instruction class */
			if (flags & F_CTRL)
			{
				if ((flags & (F_CALL|F_DIRJMP)) == (F_CALL|F_DIRJMP))
					bc = bc_call_dir;
				else if ((flags & (F_CALL|F_INDIRJMP)) == (F_CALL|F_INDIRJMP))
					bc = bc_call_indir;
				else if ((flags & (F_UNCOND|F_DIRJMP)) == (F_UNCOND|F_DIRJMP))
					bc = bc_uncond_dir;
				else if ((flags & (F_UNCOND|F_INDIRJMP))== (F_UNCOND|F_INDIRJMP))
					bc = bc_uncond_indir;
				else if ((flags & (F_COND|F_DIRJMP)) == (F_COND|F_DIRJMP))
					bc = bc_cond_dir;
				else if ((flags & (F_COND|F_INDIRJMP)) == (F_COND|F_INDIRJMP))
					bc = bc_cond_indir;
				else
				{
					//dump();
					//panic((char *)("branch has no class"));
					;
				}
				/* update instruction class profile */
				stat_add_sample(bc_prof, (int)bc);
			}
		}
#endif

#if FIXME
		if (prof_am)
		{
			enum md_amode_type am;

			/* update addressing mode pre-probe FSM */
			MD_AMODE_PREPROBE(op, fsm);

			/* compute addressing mode */
			if (flags & F_MEM)
			{
				/* compute addressing mode */
				MD_AMODE_PROBE(am, op, fsm);

				/* update the addressing mode profile */
				stat_add_sample(am_prof, (int)am);

				/* addressing mode pre-probe FSM, after all loads and stores */
				MD_AMODE_POSTPROBE(fsm);
			}
		}
#endif

#if FIXME
		if (prof_seg)
		{
			if (flags & F_MEM)
			{
				/* update instruction profile */
				stat_add_sample(seg_prof, (int)bind_to_seg(addr));
			}
		}
#endif

		if (prof_tsyms)
		{
			int tindex;

			/* attempt to bind inst address to a text segment symbol */
			sym_bind_addr(regs.regs_PC, &tindex, /* !exact */FALSE, sdb_text);

			if (tindex >= 0)
			{
				if (tindex > sym_ntextsyms){
					//panic((char *)("bogus text symbol index"));
					;
				}
				stat_add_sample(tsym_prof, tindex);
			}
			/* else, could not bind to a symbol */
		}

		if (prof_dsyms)
		{
			int dindex;

			if (flags & F_MEM)
			{
				/* attempt to bind inst address to a text segment symbol */
				sym_bind_addr(addr, &dindex, /* !exact */FALSE, sdb_data);

				if (dindex >= 0)
				{
					if (dindex > sym_ndatasyms){
						;
						//panic((char *)("bogus data symbol index"));
					}
					stat_add_sample(dsym_prof, dindex);
				}
				/* else, could not bind to a symbol */
			}
		}

		if (prof_taddr)
		{
			/* add regs_PC exec event to text address profile */
			stat_add_sample(taddr_prof, regs.regs_PC);
		}

		/* update any stats tracked by PC */
		for (i=0; i<pcstat_nelt; i++)
		{
			counter_t newval;
			int delta;

			/* check if any tracked stats changed */
			newval = STATVAL(pcstat_stats[i]);
			delta = newval - pcstat_lastvals[i];
			if (delta != 0)
			{
				stat_add_samples(pcstat_sdists[i], regs.regs_PC, delta);
				pcstat_lastvals[i] = newval;
			}

		}

		/* check for DLite debugger entry condition */
		if (dlite_check_break(regs.regs_NPC,
			is_write ? ACCESS_WRITE : ACCESS_READ,
			addr, sim_num_insn, sim_num_insn))
			dlite_main(regs.regs_PC, regs.regs_NPC, sim_num_insn, &regs, mem);

		/* go to the next instruction */
		regs.regs_PC = regs.regs_NPC;
		regs.regs_NPC += sizeof(md_inst_t);

		/* finish early? */
		if (max_insts && sim_num_insn >= max_insts)
		{
			return;
		}
	}
}

